From 478216a472527359814c4b376aecd167aa56cda0 Mon Sep 17 00:00:00 2001 From: Daniel Sabo Date: Tue, 29 Jan 2013 18:41:44 -0800 Subject: [PATCH] Minimal float -> u8, u16 conversions Add some simplistic but "accurate" float -> u8 and float -> u16 conversions to make more non-reference paths usable. The main difference from the existing conversions is that these clamp out of range values and make the path error checker happy. I also had to fudge the float-to-8bit slightly because the prior values cause it to check for the rounding on an exact 0.5 value. --- extensions/Makefile.am | 2 + extensions/gegl-fixups.c | 24 ++++++ extensions/simple.c | 164 +++++++++++++++++++++++++++++++++++++++ tests/float-to-8bit.c | 3 +- 4 files changed, 192 insertions(+), 1 deletion(-) create mode 100644 extensions/simple.c diff --git a/extensions/Makefile.am b/extensions/Makefile.am index 220d18a..2636f17 100644 --- a/extensions/Makefile.am +++ b/extensions/Makefile.am @@ -25,10 +25,12 @@ ext_LTLIBRARIES = \ fast-float.la \ naive-CMYK.la \ HSV.la \ + simple.la \ sse-fixups.la cairo_la_SOURCES = cairo.c CIE_la_SOURCES = CIE.c +expar_la_SOURCES = expar.c gegl_fixups_la_SOURCES = gegl-fixups.c gggl_lies_la_SOURCES = gggl-lies.c gggl_la_SOURCES = gggl.c diff --git a/extensions/gegl-fixups.c b/extensions/gegl-fixups.c index 5a1b972..7645993 100644 --- a/extensions/gegl-fixups.c +++ b/extensions/gegl-fixups.c @@ -465,6 +465,8 @@ conv_rgbAF_lrgba8 (unsigned char *srcc, } #define conv_rgb8_rgbAF conv_rgb8_rgbaF +#define conv_gamma_rgbaF_gamma_rgbAF conv_rgbaF_rgbAF +#define conv_gamma_rgbAF_gamma_rgbaF conv_rgbAF_rgbaF int init (void); @@ -487,6 +489,24 @@ init (void) babl_component ("Ba"), babl_component ("A"), NULL); + + + const Babl *gamma_rgbaF = babl_format_new ( + babl_model ("R'G'B'A"), + babl_type ("float"), + babl_component ("R'"), + babl_component ("G'"), + babl_component ("B'"), + babl_component ("A"), + NULL); + const Babl *gamma_rgbAF = babl_format_new ( + babl_model ("R'aG'aB'aA"), + babl_type ("float"), + babl_component ("R'a"), + babl_component ("G'a"), + babl_component ("B'a"), + babl_component ("A"), + NULL); const Babl *lrgba8 = babl_format_new ( babl_model ("RGBA"), @@ -529,6 +549,10 @@ init (void) o (rgbaF, rgbAF); o (rgbAF, rgbaF); + + o (gamma_rgbaF, gamma_rgbAF); + o (gamma_rgbAF, gamma_rgbaF); + o (rgbAF, lrgba8); o (rgb8, rgbaF); o (rgb8, rgbAF); diff --git a/extensions/simple.c b/extensions/simple.c new file mode 100644 index 0000000..bde7785 --- /dev/null +++ b/extensions/simple.c @@ -0,0 +1,164 @@ +#include +#include +#include "babl.h" + +int init (void); + +static inline long +float_to_u8 (unsigned char *src_char, unsigned char *dst, long samples) +{ + float *src = (float *)src_char; + long n = samples; + while (n--) + { + float r = src[0]; + float g = src[1]; + float b = src[2]; + float a = src[3]; + + dst[0] = (r >= 1.0f) ? 0xFF : ((r <= 0.0f) ? 0x0 : 0xFF * r + 0.5f); + dst[1] = (g >= 1.0f) ? 0xFF : ((g <= 0.0f) ? 0x0 : 0xFF * g + 0.5f); + dst[2] = (b >= 1.0f) ? 0xFF : ((b <= 0.0f) ? 0x0 : 0xFF * b + 0.5f); + dst[3] = (a >= 1.0f) ? 0xFF : ((a <= 0.0f) ? 0x0 : 0xFF * a + 0.5f); + + dst += 4; + src += 4; + } + return samples; +} + +static inline long +float_pre_to_u8_pre (unsigned char *src_char, unsigned char *dst, long samples) +{ + float *src = (float *)src_char; + long n = samples; + while (n--) + { + float r = src[0]; + float g = src[1]; + float b = src[2]; + float a = src[3]; + + if (a > 1.0f) { + r /= a; + g /= a; + b /= a; + a /= a; + } + + dst[0] = (r >= 1.0f) ? 0xFF : ((r <= 0.0f) ? 0x0 : 0xFF * r + 0.5f); + dst[1] = (g >= 1.0f) ? 0xFF : ((g <= 0.0f) ? 0x0 : 0xFF * g + 0.5f); + dst[2] = (b >= 1.0f) ? 0xFF : ((b <= 0.0f) ? 0x0 : 0xFF * b + 0.5f); + dst[3] = (a >= 1.0f) ? 0xFF : ((a <= 0.0f) ? 0x0 : 0xFF * a + 0.5f); + + dst += 4; + src += 4; + + } + return samples; +} + +static inline long +float_to_u16 (unsigned char *src_char, unsigned char *dst_char, long samples) +{ + float *src = (float *)src_char; + uint16_t *dst = (uint16_t *)dst_char; + long n = samples; + while (n--) + { + float r = src[0]; + float g = src[1]; + float b = src[2]; + float a = src[3]; + + dst[0] = (r >= 1.0f) ? 0xFFFF : ((r <= 0.0f) ? 0x0 : 0xFFFF * r + 0.5f); + dst[1] = (g >= 1.0f) ? 0xFFFF : ((g <= 0.0f) ? 0x0 : 0xFFFF * g + 0.5f); + dst[2] = (b >= 1.0f) ? 0xFFFF : ((b <= 0.0f) ? 0x0 : 0xFFFF * b + 0.5f); + dst[3] = (a >= 1.0f) ? 0xFFFF : ((a <= 0.0f) ? 0x0 : 0xFFFF * a + 0.5f); + + dst += 4; + src += 4; + } + return samples; +} + +static inline long +float_pre_to_u16_pre (unsigned char *src_char, unsigned char *dst_char, long samples) +{ + float *src = (float *)src_char; + uint16_t *dst = (uint16_t *)dst_char; + long n = samples; + while (n--) + { + float r = src[0]; + float g = src[1]; + float b = src[2]; + float a = src[3]; + + if (a > 1.0f) { + r /= a; + g /= a; + b /= a; + a /= a; + } + + dst[0] = (r >= 1.0f) ? 0xFFFF : ((r <= 0.0f) ? 0x0 : 0xFFFF * r + 0.5f); + dst[1] = (g >= 1.0f) ? 0xFFFF : ((g <= 0.0f) ? 0x0 : 0xFFFF * g + 0.5f); + dst[2] = (b >= 1.0f) ? 0xFFFF : ((b <= 0.0f) ? 0x0 : 0xFFFF * b + 0.5f); + dst[3] = (a >= 1.0f) ? 0xFFFF : ((a <= 0.0f) ? 0x0 : 0xFFFF * a + 0.5f); + + dst += 4; + src += 4; + } + return samples; +} + +int +init (void) +{ + /* float and u8 */ + babl_conversion_new (babl_format ("R'G'B'A float"), + babl_format ("R'G'B'A u8"), + "linear", + float_to_u8, + NULL); + babl_conversion_new (babl_format ("RGBA float"), + babl_format ("RGBA u8"), + "linear", + float_to_u8, + NULL); + babl_conversion_new (babl_format ("R'aG'aB'aA float"), + babl_format ("R'aG'aB'aA u8"), + "linear", + float_pre_to_u8_pre, + NULL); + babl_conversion_new (babl_format ("RaGaBaA float"), + babl_format ("RaGaBaA u8"), + "linear", + float_pre_to_u8_pre, + NULL); + + /* float and u16 */ + babl_conversion_new (babl_format ("R'G'B'A float"), + babl_format ("R'G'B'A u16"), + "linear", + float_to_u16, + NULL); + babl_conversion_new (babl_format ("RGBA float"), + babl_format ("RGBA u16"), + "linear", + float_to_u16, + NULL); + babl_conversion_new (babl_format ("R'aG'aB'aA float"), + babl_format ("R'aG'aB'aA u16"), + "linear", + float_pre_to_u16_pre, + NULL); + babl_conversion_new (babl_format ("RaGaBaA float"), + babl_format ("RaGaBaA u16"), + "linear", + float_pre_to_u16_pre, + NULL); + + return 0; +} diff --git a/tests/float-to-8bit.c b/tests/float-to-8bit.c index b273008..a93591c 100644 --- a/tests/float-to-8bit.c +++ b/tests/float-to-8bit.c @@ -86,7 +86,8 @@ main (int argc, } { - float in[][4] = {{ 0.21582, -0.55, -0.14, 1.0 }, {0.2, 0.301, 0.5, 0.6}, {0.0, 3.0, 6.0, 3.0}}; + /* (0.5 / 0.6) * 255 = 212.5, I'm not going to worry about rounding that close... */ + float in[][4] = {{ 0.21582, -0.55, -0.14, 1.0 }, {0.2, 0.301, 0.49998, 0.6}, {0.0, 3.0, 6.0, 3.0}}; unsigned char out[][4] = {{55, 0, 0, 255 }, {85,128,212,153}, {0,255,255,255}}; CHECK_CONV("float -> u8 6", unsigned char, -- 2.30.2